//-*-C++-*-
/***************************************************************************
 *
 *   Copyright (C) 2008-2025 by Willem van Straten and Andrew Jameson
 *   Licensed under the Academic Free License version 2.1
 *
 ***************************************************************************/

#ifndef __dsp_TScrunch_h
#define __dsp_TScrunch_h

#include "dsp/Transformation.h"
#include "dsp/TimeSeries.h"

namespace dsp {

  //! Decimates a TimeSeries in the time domain

  /*! Input data are buffered to handle block sizes that are not integer
      multiples of the decimation factor (number of samples)
  */

  class TScrunch : public Transformation <TimeSeries, TimeSeries>
  {

  public:

    TScrunch (Behaviour place=anyplace);

    void set_factor ( unsigned samples );
    unsigned get_factor () const;

    void set_time_resolution ( double microseconds );
    double get_time_resolution () const;

    class Engine;

    void set_engine (Engine*);

  protected:

    //! Prepare all relevant attributes
    void prepare ();

    //! Reserve the maximum amount of output space required
    void reserve ();

    //! Prepare the output TimeSeries
    void prepare_output ();

    //! Perform decimation
    void transformation ();
    void tfp_tscrunch ();
    void fpt_tscrunch ();

    mutable unsigned factor;
    mutable double time_resolution;

    // If true, use the tres parameter, if false use the factor parameter
    mutable bool use_tres;

    unsigned sfactor;
    uint64_t output_ndat;
    bool prepared;

    Reference::To<Engine> engine;
  };

  class TScrunch::Engine : public OwnStream
  {
  public:

    /**
     * @brief Perform a temporal scrunch by the sfactor from the input timeseries to the output
     * timeseries where both have FPT ordering
     *
     * @param in input timeseries to read
     * @param out output timeseries to write, after tscrunching
     * @param sfactor number of input time samples to sum into each output time sample
     */
    virtual void fpt_tscrunch (const dsp::TimeSeries * in,
                         dsp::TimeSeries * out,
                         unsigned sfactor) = 0;

    /**
     * @brief Perform a temporal scrunch by the sfactor from the input timeseries to the output
     * timeseries where both have TFP ordering.
     *
     * @param in input timeseries to read
     * @param out output timeseries to write, after tscrunching
     * @param sfactor number of input time samples to sum into each output time sample
     */
    virtual void tfp_tscrunch (const dsp::TimeSeries * in,
                         dsp::TimeSeries * out,
                         unsigned sfactor) = 0;

  };

} // namespace dsp

#endif // !defined(__dsp_TScrunch_h)
